import os
import sys
import datetime

# 添加项目根目录到路径
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))

from PySide6.QtWidgets import (
    QDialog,
    QVBoxLayout,
    QHBoxLayout,
    QPushButton,
    QLabel,
    QGraphicsView,
    QGraphicsScene,
    QMessageBox,
)
from PySide6.QtGui import QPixmap, QImage, QPainter
from PySide6.QtCore import Qt, QRectF, QPointF


class ImageViewerDialog(QDialog):
    """图像查看器对话框，用于显示图像并提供放大、缩小等功能"""

    def __init__(self, parent=None, image=None, title="图像查看器", results=None):
        """
        初始化图像查看器对话框

        参数:
            parent: 父窗口
            image: 要显示的图像，可以是QImage或QPixmap
            title: 对话框标题
            results: 识别结果列表
        """
        super().__init__(parent)
        self.setWindowTitle(title)
        self.setMinimumSize(800, 600)

        self.image = image
        self.results = results

        # 创建布局
        self.setup_ui()

        # 加载图像
        if image is not None:
            self.load_image(image)

    def setup_ui(self):
        """设置UI组件"""
        # 创建主布局
        self.layout = QVBoxLayout(self)

        # 创建工具栏
        self.toolbar_layout = QHBoxLayout()

        # 添加缩放按钮
        self.zoom_in_btn = QPushButton("放大(+)")
        self.zoom_out_btn = QPushButton("缩小(-)")
        self.fit_view_btn = QPushButton("适应窗口(F)")
        self.actual_size_btn = QPushButton("实际大小(1)")
        self.save_btn = QPushButton("保存图像(S)")

        # 添加工具栏按钮到布局
        self.toolbar_layout.addWidget(self.zoom_in_btn)
        self.toolbar_layout.addWidget(self.zoom_out_btn)
        self.toolbar_layout.addWidget(self.fit_view_btn)
        self.toolbar_layout.addWidget(self.actual_size_btn)
        self.toolbar_layout.addWidget(self.save_btn)
        self.toolbar_layout.addStretch(1)

        # 添加工具栏到主布局
        self.layout.addLayout(self.toolbar_layout)
        
        # 创建信息标签
        self.info_label = QLabel(self)
        self.info_label.setStyleSheet("background-color: rgba(255, 255, 255, 0.8); padding: 10px; border-radius: 5px;")
        self.info_label.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.info_label.setWordWrap(True)
        self.info_label.setVisible(False)
        self.layout.addWidget(self.info_label)

        # 创建QGraphicsView和QGraphicsScene
        self.scene = QGraphicsScene(self)
        self.view = QGraphicsView(self.scene, self)

        # 设置高质量渲染选项
        self.view.setRenderHints(
            QPainter.Antialiasing
            | QPainter.SmoothPixmapTransform
            | QPainter.TextAntialiasing
        )

        # 设置视口更新模式为FullViewportUpdate，提高渲染质量
        self.view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)

        # 禁用抗锯齿调整，提高性能
        self.view.setOptimizationFlags(
            QGraphicsView.DontAdjustForAntialiasing | QGraphicsView.DontSavePainterState
        )

        # 启用缓存背景，提高性能
        self.view.setCacheMode(QGraphicsView.CacheBackground)

        # 启用鼠标跟踪和滚轮缩放
        self.view.setDragMode(QGraphicsView.ScrollHandDrag)
        self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.view.setResizeAnchor(QGraphicsView.AnchorUnderMouse)

        # 添加视图到布局
        self.layout.addWidget(self.view)

        # 添加状态栏显示鼠标位置和缩放比例
        self.status_bar = QLabel(self)
        self.status_bar.setStyleSheet("background-color: #f0f0f0; padding: 3px;")
        self.layout.addWidget(self.status_bar)

        # 连接信号槽
        self.connect_signals()

    def connect_signals(self):
        """连接信号和槽"""
        # 工具栏按钮事件
        self.zoom_in_btn.clicked.connect(self.zoom_in)
        self.zoom_out_btn.clicked.connect(self.zoom_out)
        self.fit_view_btn.clicked.connect(self.fit_to_view)
        self.actual_size_btn.clicked.connect(self.actual_size)
        self.save_btn.clicked.connect(self.save_image)

        # 自定义事件处理
        self.view.wheelEvent = self.wheel_event
        self.view.mouseMoveEvent = self.mouse_move_event
        self.keyPressEvent = self.key_press_event
        self.resizeEvent = self.resize_event

    def load_image(self, image, info_text=None):
        """加载图像到视图

        Args:
            image: QImage或QPixmap对象
            info_text: 可选的信息文本
        """
        # 将QImage转换为QPixmap（如果需要）
        if isinstance(image, QImage):
            pixmap = QPixmap.fromImage(image)
        else:
            pixmap = image

        if pixmap.isNull():
            QMessageBox.warning(self, "错误", "无法加载图像")
            self.close()
            return

        # 清除之前的场景内容
        self.scene.clear()

        # 添加图像到场景
        self.scene.addPixmap(pixmap)
        self.scene.setSceneRect(0, 0, pixmap.width(), pixmap.height())
        
        # 设置图像视图
        self.view.setScene(self.scene)
        
        # 保存当前图像
        self._current_pixmap = pixmap
        
        # 初始缩放
        self.scale_to_40_percent()
        
        # 更新信息标签
        if info_text:
            self.info_label.setText(info_text)
            self.info_label.setVisible(True)
        else:
            self.info_label.setVisible(False)

    def scale_to_40_percent(self):
        """缩放到40%"""
        if hasattr(self, "_current_pixmap"):
            self.view.resetTransform()
            self.view.scale(0.4, 0.4)
            # 使用场景矩形的中心点而不是直接传递pixmap对象
            scene_center = self.scene.sceneRect().center()
            self.view.centerOn(scene_center)
            self.update_status_bar()

    def zoom_in(self):
        """放大图像"""
        self.view.scale(1.2, 1.2)
        self.update_status_bar()

    def zoom_out(self):
        """缩小图像"""
        self.view.scale(0.8, 0.8)
        self.update_status_bar()

    def fit_to_view(self):
        """适应窗口"""
        if hasattr(self, "_current_pixmap"):
            # 使用场景矩形而不是直接传递pixmap对象
            self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)
            self.update_status_bar()

    def actual_size(self):
        """实际大小"""
        if hasattr(self, "_current_pixmap"):
            self.view.resetTransform()
            # 使用场景矩形的中心点而不是直接传递pixmap对象
            scene_center = self.scene.sceneRect().center()
            self.view.centerOn(scene_center)
            self.update_status_bar()

    def wheel_event(self, event):
        """鼠标滚轮事件处理"""
        # 确定缩放因子
        factor = 1.2
        if event.angleDelta().y() < 0:
            factor = 1.0 / factor

        # 应用缩放
        self.view.scale(factor, factor)

        # 防止过度放大或缩小
        transform = self.view.transform()
        scale = transform.m11()  # 水平缩放因子

        # 限制缩放范围
        if scale < 0.1:
            self.view.resetTransform()
            self.view.scale(0.1, 0.1)
        elif scale > 10.0:
            self.view.resetTransform()
            self.view.scale(10.0, 10.0)

        self.update_status_bar()

    def mouse_move_event(self, event):
        """鼠标移动事件处理"""
        if hasattr(self, "_current_pixmap"):
            # 获取视图坐标
            view_pos = event.pos()
            # 转换为场景坐标
            scene_pos = self.view.mapToScene(view_pos)

            # 获取当前缩放比例
            transform = self.view.transform()
            scale = transform.m11() * 100  # 转为百分比

            # 确保坐标在图像范围内
            if (
                scene_pos.x() >= 0
                and scene_pos.y() >= 0
                and scene_pos.x() < self._current_pixmap.width()
                and scene_pos.y() < self._current_pixmap.height()
            ):
                status_text = f"位置: ({int(scene_pos.x())}, {int(scene_pos.y())}) | 缩放: {scale:.0f}%"
            else:
                status_text = f"缩放: {scale:.0f}%"

            self.status_bar.setText(status_text)

        # 调用原始事件处理
        QGraphicsView.mouseMoveEvent(self.view, event)

    def update_status_bar(self):
        """更新状态栏显示的缩放比例"""
        if hasattr(self, "view"):
            transform = self.view.transform()
            scale = transform.m11() * 100  # 转为百分比
            self.status_bar.setText(f"缩放: {scale:.0f}%")

    def key_press_event(self, event):
        """键盘事件处理"""
        if hasattr(self, "_current_pixmap"):
            if event.key() == Qt.Key_Plus or event.key() == Qt.Key_Equal:
                self.zoom_in()
            elif event.key() == Qt.Key_Minus:
                self.zoom_out()
            elif event.key() == Qt.Key_F:
                self.fit_to_view()
            elif event.key() == Qt.Key_1:
                self.actual_size()
            elif event.key() == Qt.Key_4:  # 添加快捷键4以设置为40%缩放
                self.scale_to_40_percent()
            elif event.key() == Qt.Key_S:  # 添加快捷键S保存图像
                self.save_image()
            elif event.key() == Qt.Key_Escape:
                self.close()
            else:
                QDialog.keyPressEvent(self, event)
        else:
            QDialog.keyPressEvent(self, event)

    def resize_event(self, event):
        """窗口大小改变事件处理"""
        # 只在首次调整大小时设置40%缩放
        if not hasattr(self, "_resized") and hasattr(self, "_current_pixmap"):
            self.scale_to_40_percent()
            self._resized = True
        QDialog.resizeEvent(self, event)

    def save_image(self):
        """保存当前图像"""
        if not hasattr(self, "_current_pixmap") or self._current_pixmap.isNull():
            QMessageBox.warning(self, "警告", "没有可保存的图像")
            return
            
        # 获取系统图片文件夹路径
        pictures_dir = os.path.join(os.path.expanduser("~"), "Pictures")
        if not os.path.exists(pictures_dir):
            # 尝试中文路径
            pictures_dir = os.path.join(os.path.expanduser("~"), "图片")
            if not os.path.exists(pictures_dir):
                # 如果找不到，使用当前目录
                pictures_dir = os.getcwd()

        # 生成文件名：recognition_年月日_时分秒.png
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"recognition_{timestamp}.png"
        filepath = os.path.join(pictures_dir, filename)
        
        # 保存图像
        if self._current_pixmap.save(filepath, "PNG"):
            QMessageBox.information(
                self, "保存成功", f"图像已保存到:\n{filepath}"
            )
            self.status_bar.setText(f"图像已保存: {filename}")
        else:
            QMessageBox.critical(
                self, "保存失败", f"无法保存图像到:\n{filepath}"
            )
